module Hibernate
  PropertySpecifier = Struct.new :name, :type, :column

  module Configuration
    def define_hibernate_variable(name, default_value)
      # self references an object of class Class	
      self.instance_variable_set :"@#{name}", default_value
      (class <<self; self; end).send :define_method, :"#{name}" do
        instance_variable_get :"@#{name}"
      end
      (class <<self; self; end).send :define_method, :"#{name}=" do |val|
        instance_variable_set :"@#{name}", val
      end
    end

    def find(*args)
      if args.first == :all
        ActiveHibernate.execute do |session|
          session.createQuery("from #{self.persistent_class.entity_name}").list
        end
      else
        ActiveHibernate.execute do |session|
          session.get(self.persistent_class.entity_name,args.first)
        end
      end
    end

    def hattr_accessor(name, type, column=name)
      self.persistent_class.property_collection << ActiveHibernate::Property.new(name.to_sym, type.to_sym, column.to_sym)
      attr_accessor name
    end
	
    def primary_key_accessor(name, type, options={})
      column = options.delete(:pk_column) || name
      self.persistent_class.identity = ActiveHibernate::Identity.new(name.to_sym, type.to_sym, column.to_sym, options)
      attr_accessor name
    end
		
    def with_table_name(name)
      self.persistent_class.table_name = name
    end
		
    def join_with_table(table_name=nil,key_column=nil)
      self.persistent_class.create_join(table_name,key_column)
      yield if block_given?
      self.persistent_class.reset_join
    end
    
    def h_component(name,mapping,class_name=nil)
      self.persistent_class.component_collection << ActiveHibernate::Component.new(name,mapping,class_name)
      attr_accessor name
    end
    
    def many_to_one(name,entity_name=nil,column=nil)
      self.persistent_class.many_to_one_collection << ActiveHibernate::ManyToOne.new(name,entity_name, column)
      attr_accessor name
    end
    
    def one_to_many(name,entity_name=nil,column=nil)
      self.persistent_class.add_one_to_many(ActiveHibernate::OneToMany.new(name,entity_name, column))
      attr_accessor name
    end
  end

  def self.included(c)
    # c is an object of class Class
    c.extend Configuration
    c.define_hibernate_variable(:persistent_class, ActiveHibernate::PersistentRootClass.new(c))
    ActiveHibernate.add_hibernated_class(c.persistent_class)
    
    c.instance_eval &(DB_CONFIG[:pk_strategy])
  
    c.class_eval do
      def self.inherited(subclass)
        entity_name = self.name.split('::').join('.')
        subclass.extend Configuration
        subclass.define_hibernate_variable(:persistent_class, ActiveHibernate::PersistentSubClass.new(subclass))
        subclass.persistent_class.super_entity_name = entity_name
        ActiveHibernate.add_hibernated_class(subclass.persistent_class)		
      end 
    end	
	  
  end

  def destroy
    ActiveHibernate.execute { |session|
      session.delete self
    }
  end

  def save
    ActiveHibernate.execute { |session|
      session.saveOrUpdate self
      self.id
    }
  end
end
